#include "task_group.h"

#include <core/sharedata/login_data.h>

#include <algorithm>

#include "login_authority_task.h"
#include "login_connect_task.h"
#include "login_gw_verify_task.h"
#include "login_verify_task.h"

#define FAIL_TRY_COUNT 3

namespace qb {
CTaskGroup::CTaskGroup(int nType)
    : m_nCurrentTask(-1),
      m_nTrys(0),
      m_pLoginConnectTask(NULL),
      m_pLoginVerifyTask(NULL),
      m_pGWConnectTask(NULL),
      m_pLoginGwVerifyTask(NULL),
      m_pLoginAuthorityTask(NULL) {}

CTaskGroup::~CTaskGroup() { m_tasks.clear(); }

CTask* CTaskGroup::GetCurrentTask() const {
  if (m_nCurrentTask >= 0 &&
      m_nCurrentTask < static_cast<int>(m_tasks.size())) {
    std::list<CTask*>::const_iterator it = m_tasks.begin();
    std::advance(it, m_nCurrentTask);
    return *it;
  }
  return NULL;
}

void CTaskGroup::Append(CTask* pTask) {
  if (pTask) {
    std::list<CTask*>::const_iterator it =
        std::find(m_tasks.begin(), m_tasks.end(), pTask);
    if (it == m_tasks.end()) {
      m_tasks.push_back(pTask);
      pTask->SetObserver(this);
    }
  }
}

bool CTaskGroup::IsAllTaskFinished() {
  int nCount = static_cast<int>(m_tasks.size());
  if (nCount <= 0) {
    return true;
  }
  return (m_nCurrentTask >= (nCount - 1));
}

bool CTaskGroup::OnNetData(char* pData, int nDataLen) {
  CTask* pTask = GetCurrentTask();
  QB_CHECK_RETURN_BOOL1(pTask);

  pTask->OnRecvNetData(pData, nDataLen);
  return true;
}

bool CTaskGroup::OnNetStatus(int32_t status) {
  CTask* pTask = GetCurrentTask();
  QB_CHECK_RETURN_BOOL1(pTask);

  pTask->OnRecvNetStatus(status);
  return true;
}

void CTaskGroup::StartNextTask() {
  if (++m_nCurrentTask >= 0 &&
      m_nCurrentTask < static_cast<int>(m_tasks.size())) {
    std::list<CTask*>::iterator it = m_tasks.begin();
    std::advance(it, m_nCurrentTask);

    m_nTrys = 0;
    (*it)->Start();
  } else {
    std::list<ITaskGroupObserver*>::iterator itObserver;
    for (itObserver = m_listObserver.begin();
         itObserver != m_listObserver.end(); itObserver++) {
      if (*itObserver) {
        (*itObserver)->OnAllTaskFinished();
      }
    }
  }
}

void CTaskGroup::OnTaskStep(qb::NetStatus status, short ret_code) {
  std::list<ITaskGroupObserver*>::iterator itObserver;
  for (itObserver = m_listObserver.begin(); itObserver != m_listObserver.end();
       itObserver++) {
    if (*itObserver) {
      (*itObserver)->OnTaskStep(status, ret_code);
    }
  }
}

void CTaskGroup::OnTaskFinished(CTask* pTask) { StartNextTask(); }

void CTaskGroup::OnTaskFailed(CTask* /*pTask*/, qb::NetStatus status,
                              short ret_code) {
  CTask* pTask = GetCurrentTask();
  QB_CHECK_RETURN_VOID1(pTask);

  if (!pTask->IsConnectTask()) {
    std::list<ITaskGroupObserver*>::iterator itObserver;
    for (itObserver = m_listObserver.begin();
         itObserver != m_listObserver.end(); itObserver++) {
      if (*itObserver) {
        (*itObserver)->OnTaskGroupFailed(status, ret_code);
      }
    }
  } else {
    if (++m_nTrys > FAIL_TRY_COUNT) {
      std::list<ITaskGroupObserver*>::iterator itObserver;
      for (itObserver = m_listObserver.begin();
           itObserver != m_listObserver.end(); itObserver++) {
        if (*itObserver) {
          (*itObserver)->OnTaskGroupFailed(status, ret_code);
        }
      }

      return;
    }

    pTask->Start();
  }
}

int32_t CTaskGroup::StartLoginSteps() {
  if (-1 != BuildLoginSteps()) {
    return RunLoginSteps();
  }

  return -1;
}

int32_t CTaskGroup::BuildLoginSteps() {
  ///////////////////////////////////////////////////////////////////////
  // 第一步: 连接登录服务器
  if (!m_pLoginConnectTask) {
    m_pLoginConnectTask = new CLoginConnectTask();
    QB_CHECK_RETURN_VALUE(m_pLoginConnectTask, -1);
    Append(m_pLoginConnectTask);
  }

  ///////////////////////////////////////////////////////////////////////
  // 第二步: 登录服务器验证
  if (!m_pLoginVerifyTask) {
    m_pLoginVerifyTask = new CLoginVerifyTask();
    QB_CHECK_RETURN_VALUE(m_pLoginVerifyTask, -1);
    Append(m_pLoginVerifyTask);
  }

  ///////////////////////////////////////////////////////////////////////
  // 第三步: 连接网关服务器
  if (!m_pGWConnectTask) {
    m_pGWConnectTask = new CLoginConnectTask();
    QB_CHECK_RETURN_VALUE(m_pGWConnectTask, -1);
    Append(m_pGWConnectTask);
  }

  ///////////////////////////////////////////////////////////////////////
  // 第四步: 网关服务器验证
  if (!m_pLoginGwVerifyTask) {
    m_pLoginGwVerifyTask = new CLoginGwVerifyTask();
    QB_CHECK_RETURN_VALUE(m_pLoginGwVerifyTask, -1);
    Append(m_pLoginGwVerifyTask);
  }

  ///////////////////////////////////////////////////////////////////////
  // 第五步: 请求用户权限
  if (!m_pLoginAuthorityTask) {
    m_pLoginAuthorityTask = new CLoginAuthorityTask();
    QB_CHECK_RETURN_VALUE(m_pLoginAuthorityTask, -1);
    Append(m_pLoginAuthorityTask);
  }

  return 0;
}

int32_t CTaskGroup::RunLoginSteps() {
  StartNextTask();
  return 0;
}

void CTaskGroup::StopLoginSteps() {
  m_nCurrentTask = -1;

  if (m_pLoginConnectTask) {
    m_pLoginConnectTask->Terminate();
  }

  if (m_pLoginVerifyTask) {
    m_pLoginVerifyTask->Terminate();
  }

  if (m_pGWConnectTask) {
    m_pGWConnectTask->Terminate();
  }

  if (m_pLoginGwVerifyTask) {
    m_pLoginGwVerifyTask->Terminate();
  }

  if (m_pLoginAuthorityTask) {
    m_pLoginAuthorityTask->Terminate();
  }
}

void CTaskGroup::DeleteTaskGroups() {
  m_tasks.clear();

  if (m_pLoginConnectTask) {
    delete m_pLoginConnectTask;
    m_pLoginConnectTask = NULL;
  }

  if (m_pLoginVerifyTask) {
    delete m_pLoginVerifyTask;
    m_pLoginVerifyTask = NULL;
  }

  if (m_pGWConnectTask) {
    delete m_pGWConnectTask;
    m_pGWConnectTask = NULL;
  }

  if (m_pLoginGwVerifyTask) {
    delete m_pLoginGwVerifyTask;
    m_pLoginGwVerifyTask = NULL;
  }
}

}  // namespace qb
